#pragma once

#include <vector>
#include <set>
#include "config.h"
using namespace std;

class Follows{
public:
	/** Constructor
	 * Creates an empty Follows table.
	 */
	Follows();
	
	/**
	 * Add a Follows relationship of statement number 1 followed by statement number 2.
	 * @param stmtNum1 statement number one, the preceding statement.
	 * @param stmtNum2 statement number two, the following statement.
	 * @return the index of newly added Follows relationship, -1 if unsuccessful.
	 */
	int addFollows(int stmtNum1, int stmtNum2);

	/**
	 * Get a list of all matching statement pairs that directly follows each other.
	 * @param stmtNum1 the preceding statement number, can be ANYVALUE.
	 * @param stmtNum2 the following statement number, can be ANYVALUE.
	 * @return a vector of pairs that satisfies the criteria, empty if none satisfies.
	 */
	vector<pair<int, int>> getFollows(int stmtNum1, int stmtNum2);
	
	/**
	 * Get a list of all matching statement pairs that directly or undirectly follows each other.
	 * @param stmtNum1 the preceding statement number, can be ANYVALUE.
	 * @param stmtNum2 the following statement number, can be ANYVALUE.
	 * @return a vector of pairs that satisfies the criteria, empty if none satisfies.
	 */
	vector<pair<int, int>> getFollowsStar(int stmtNum1, int stmtNum2);

private:
	vector<pair<int, int>> followsIndex; /**< A Follows table that contains all pairs of following statements */
	vector<vector<int>> followsChainIndex; /**< A Follows table that contains chain of following statements */

	/**
	 * Given a list of matching statement numbers, build corresponding pairs.
	 * @param result the location where pairs will be stored.
	 * @param input the list of matching statement numbers.
	 * @param fixFirstOrLast determine if build follows(firstElement, n) or follows(n, lastElement).
	 */
	void buildPairs(set<pair<int, int>> &result, vector<int> input, int fixFirstOrLast);

	/**
	 * Given a list of matching statement numbers, build a list of meshed pairs.
	 * @param result the location where pairs will be stored.
	 * @param input the list of matching statement numbers.
	 */
	void Follows::buildMeshPairs(set<pair<int, int>> &result, vector<int> input);
};